/*
-----------------------------------------------------------------------------
This header file is part of command agent
The project of Engineering Lab, dept. of CSIE, NTNU.

Copyright (c) 2000-2006 The Engineering Lab, dept. of CSIE, NTNU.
-----------------------------------------------------------------------------
Filename:    Command_Agent.h
Description: This is the header file of command agent. Command agent is responsible for 
             completing the commands from DIVA UI and JDB through network and interacts 
			 with Watched Object Pool (WOP). 
Written by:  Ming Jie Chiou.
Last update: 2006/12/25
Update Note: 12/19 - Complete the visualize, unfold method.
             12/22 - Complete the dummy wop server thread and dummy jdb server thread.
			 12/25 - Complete the dummy wopm.
			 12/26 - Add two method: getType and getName for wopm.
			       - Combine with JDB server thread. Changing the wop server thread to client.
		     12/28 - Add parseType and rename the method parseHashCode to parseValue.
			 //== 2007 ==//
			 02/10 - Add the method unfold1D and unfold2D.
			 02/17 - Add the method intToString to convert the integer to the string.
			 02/27 - Remove the method search.
			 02/28 - Add the method getArrayLength to get the array length from yaJDB.
			 03/01 - Add the method unfold3D.
			 03/03 - *Define all the command such as ask, show to the format CMD_ASK, CMD_SHOW.
			         *Add the method newObjEntry to minus the code copied in the command_agent.cpp.
					 *Combine the method unfold1D, unfold2D, unfold3D to the method unfoldArray
					 *Add the method getUnfoldLevel to get the unfold level which one, two or three dimension.
			 03/04 - *Remove the method unfold. Move the part of code to the unfoldRef.

-----------------------------------------------------------------------------
*/


/*------------------------------------------------------------*/
#ifndef _Command_Agent_H_
#define	_Command_Agent_H_
/*------------------------------------------------------------*/
#include <iostream>
#include <vector>
#include "all_entries.h"
#include "Socket.h"
#include <QtCore/QObject>

class DIVA_VM;


//--- -------- will move to the global.h one day
//             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ what day???
// connect info
#define CONNECT_IP "127.0.0.1"
#define CONNECT_PORT 2001

// flag
#define BLANK " "
#define NEWLINE "\n"
#define DOT "."
#define FLAG_AT "@"
#define FLAG_MARK "\""

//command
#define CMD_VISUALIZE "visualize"
#define CMD_UNFOLD "unfold"
#define CMD_FOLD "fold"
#define CMD_UPDATE "update"
#define CMD_UNFOLD3D "unfold3D"
#define CMD_UNFOLD2D "unfold2D"
#define CMD_UNFOLD1D "unfold1D"
#define PRINT "<print>"

#define CMD_START "<start>"
#define CMD_END "<end>"
#define CMD_SYNC_START "<sync_start>"
#define CMD_SYNC_END "<sync_end>"
#define CMD_ASK "ask "
#define CMD_ADDR "addr "
#define CMD_SHOW "show "
#define CMD_STRUCT "struct "
#define CMD_SCOPE "scope "
#define CMD_SCRIPT_VM_DONE "SVM_DONE"
#define CMD_GET_LINE "line"

#define TAG_VALUE "<VALUE>"
#define TAG_ATTNAME "ATTNAME"
#define TAG_USRTYPE "USRTYPE"

#define TYPE_ARRAY "ARRTYPE"
#define TYPE_REF "REFTYPE"
#define TYPE_PRI "PRITYPE"

#define VARNAME "<VARNAME>"
#define VARTYPE "<VARTYPE>"
#define ADDR    "<ADDR>"
#define ATTNO   "<ATTQUN>" 
#define CLASSNAME "<CLASSNAME>"
#define VALUE "<VALUE>" 

//-----------


using namespace std;


//class Command_Agent: public Singleton<Command_Agent>{
class Command_Agent: public QObject {
	Q_OBJECT
private:
	
    static Command_Agent* ca;
	Command_Agent( const std::string & clientIP );

	std::vector<DIVA_VM*> tempC;
public:
	/// constructor & destructor
	
	~Command_Agent();

	// singleton method
	static void initialize( const std::string & clientIP );
	static Command_Agent* getInstance();
	/// singleton method
	//static Command_Agent& getSingleton(void);
	//static Command_Agent* getSingletonPtr(void);

	/// visualize
	WOP_Entry*  visualize(std::string );
	WOP_Entry*  visualize(std::string, WOP_Entry *parent );
	WOP_Entry*  retrieveWOP(std::string, WOP_Entry *parent, WOP_Entry* from, bool top, std::string known_vartype);

	/// fold
	void fold(std::string );

	/// update
	void update();

	/// unfoldRef
	void unfoldRef(std::string );
	WOP_Entry * unfoldRef(WOP_Entry *refen);
	WOP_Entry* unfoldRefPure(WOP_Entry*);
	
	void unfoldObject(WOP_Obj_Entry *shell, bool top) ;
	WOP_Entry * unfoldObject( WOP_Entry * objen );
	WOP_Entry * unfoldObjPure( WOP_Entry * objen );
	/// unfoldArray
	void unfoldArray(std::string );
	void unfoldArray(WOP_Array_Entry *en, bool top);

	// given a vartype string, this method return its wop type
	std::string Command_Agent::determine_wop_type(std::string vartype) ;
	
	// getvalue- for wopm
	std::string getValue(std::string );

	/** give a variable name, this method return true if the variable is still in scope */
	bool check_scope(std::string s) ;

	std::string getClassName(std::string );

	/// stringSplit - split the string return from yaJDB
	std::vector<std::string> stringSplit(std::string, std::string );

	/// intToString - convert int to string
	std::string intToString(int);

	/// getArrayLength - get the array's length by the give name
	int getArrayLength(std::string );

	/// newObjEntry - new the object entry and add into the wopm
	WOP_Entry* newObjEntry(std::string name, WOP_Entry* parent, WOP_Entry* from, bool top, std::string vartype, std::string addr );
	void reviveObjEntry(WOP_Entry *en, std::string _visualItem, WOP_Entry* from) ;
	void reviveUnfoldedObject(WOP_Obj_Entry *shell, bool top) ;

	// new ArrayEntry - new the array entry 
	WOP_Entry* newArrayEntry(std::string _visualItem, WOP_Entry* parent_wop, WOP_Entry* from, bool top, std::string vartype, std::string addr) ;
    void reviveUnfoldedArray(WOP_Array_Entry *shell, bool top) ;
	void reviveArrayEntry(WOP_Entry* en, string  _visualItem, WOP_Entry* from) ;
	/// getUnfoldLevel
	int getUnfoldLevel(std::string );

	// check sleep wops and make its paired VM invisible
	void hideOutofScopeVMs() ;
		
	/// makeChildName - make the child entry's name by the array level
	std::string makeChildName(int, int, int, int ); // unfoldLevel,currentLevel,coorX2,coorY2

	/// checkUnfold - check if the object entry is already existed.
	bool checkUnfold(std::string );

	/// auto unfold the given entry
	std::vector<WOP_Entry* > autoUnfold(WOP_Entry* );

	void sendStepMsg();
	void sendNextMsg();
	void sendContMsg();
	void sendOverMsg();
	static Command_Agent* getCommand_Agent();

	void sendSVMMsg(); // add by hyt
	std::string sendGetLineMsg();// add by hyt
	int getLineNumber(); //add by hyt
	void  printMessage(std::string); //add by howway

protected:

	/// get the message return from the jdb server thread
	std::string msg;

	/// socket connect to the jdb server thread
	SocketClient* socket_s;

	/// port 
	int port;

	/// ip connected to the jdb server thread
	std::string connectIP;

	//add by hyt , 決定現在visualize的變數是不是minerva script 設定的, script是預先寫好要visualize的變數 , 並非為手動輸入visualize的變數
	bool scriptmode;

private slots:
	void onVisualize( const QString & variableName );
	void onUpdate();
	void onAnime(const QString & variableName);
};

/*------------------------------------------------------------*/
#endif //#ifndef _Command_Agent_H_
/*------------------------------------------------------------*/